package com.jhf.youke.core.config;

import com.google.common.collect.ImmutableMap;
import com.jhf.youke.core.exception.DomainException;
import feign.FeignException;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.util.NestedServletException;

import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 全局异常捕获
 * @author RHJ
 */
@Slf4j
@RestControllerAdvice
public class ExceptionConfig {

    @ExceptionHandler(FeignException.class)
    private ResponseEntity<?> catchFeignException(FeignException e) {
        return ResponseEntity.status(e.status())
                .header("Content-Type", "application/json;UTF-8")
                .body(e.responseBody().isPresent() ? StandardCharsets.UTF_8.decode(e.responseBody().get()).toString() : ImmutableMap.of(
                        "code", -1,
                        "error", "服务不可用"
                ));
    }

    @ExceptionHandler(value = DomainException.class)
    public Map<String, Object> catchDomainException(DomainException ex, HttpServletResponse response) {
        log.error("uncaught error", ex);
        response.setStatus(200);
        response.setContentType("application/json;UTF-8");
        return Map.of(
                "code", -1,
                "error", ex.getMessage()
        );
    }

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Map<String, Object> catchMethodArgumentNotValidException(MethodArgumentNotValidException ex, HttpServletResponse response) {
        response.setStatus(200);
        String error = ex.getBindingResult().getFieldErrors().stream().map(fieldError -> fieldError.getField() + fieldError.getDefaultMessage()).collect(Collectors.joining(", "));
        return Map.of(
                "code", -1,
                "error", error
        );
    }

    @ExceptionHandler(value = NestedServletException.class)
    public Map<String, Object> assertionError(NestedServletException ex, HttpServletResponse response) {
        response.setStatus(200);
        response.setContentType("application/json;UTF-8");
        return Map.of(
                "code", -1,
                "error", ex.getCause().getMessage()
        );
    }

    @ExceptionHandler(value = Exception.class)
    public Map<String, Object> catchException(Exception ex, HttpServletResponse response) {
        log.error("uncaught error", ex);
        response.setStatus(200);
        response.setContentType("application/json;UTF-8");
        return Map.of(
                "code", -1,
                "error", "接口请求异常，请联系管理员"
        );
    }


}
